package core

import (
	"bytes"
	"errors"
	"io"
	"log"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"strings"

	// "github.com/gofiber/fiber/v2/middleware/csrf"
	xls "github.com/shakinm/xlsReader/xls"
	"github.com/tealeg/xlsx"
	// "main/src/models"
)

type AuthSession struct {
	Cookies []*http.Cookie
	Csrf    string
	Err     error
}

// func for auth in site with POST and crf token
func ES2Auth(uri string, login string, password string) AuthSession {
	authSession := AuthSession{}
	loginURL, err := url.Parse(uri)
	if err != nil {
		log.Println(err)
		authSession.Err = err
		return authSession
	}

	getReq, err := http.NewRequest("GET", loginURL.String(), nil)
	if err != nil {
		log.Println(err)
		authSession.Err = err
		return authSession
	}

	getReq.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36")
	cookieJar, _ := cookiejar.New(nil)
	client := &http.Client{Jar: cookieJar}
	getRes, err := client.Do(getReq)
	var csrfToken string
	if err != nil {
		log.Println(err)
		authSession.Err = err
		return authSession
	}
	defer getRes.Body.Close()

	for _, cookie := range getRes.Cookies() {
		if cookie.Name == "csrftoken" {
			csrfToken = cookie.Value
			authSession.Csrf = csrfToken
		}
	}

	data := url.Values{
		"csrfmiddlewaretoken": {csrfToken},
		"username":            {login},
		"password":            {password},
	}
	authReq, err := http.NewRequest("POST", loginURL.String(), strings.NewReader(data.Encode()))
	if err != nil {
		log.Println(err)
		authSession.Err = err
		return authSession
	}
	authReq.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36")
	authReq.Header.Set("Referer", "https://ruobr.ru/accounts/login/")
	authReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	// authReq.PostForm = data
	authRes, err := client.Do(authReq)
	if err != nil {
		log.Println(err)
		authSession.Err = err
		return authSession
	}
	defer authRes.Body.Close()

	body, err := io.ReadAll(authRes.Body)
	if err != nil {
		authSession.Err = err
		return authSession
	}
	if !strings.Contains(string(body), "<a class=\"item\" href=\"/accounts/logout/\">Выход</a>") {
		err := errors.New("авторизация в ЭШ 2.0 не удалась")
		log.Println(err)
		authSession.Err = err
		return authSession
	}
	// log.Println(body)
	authSession.Cookies = authRes.Cookies()

	return authSession
}

func DownloadFile(uri string, cookies []*http.Cookie) ([]byte, error) {
	loginURL, err := url.Parse(uri)
	pageURL := loginURL.Scheme + "://" + loginURL.Host + loginURL.Path
	cookieJar, _ := cookiejar.New(nil)
	client := &http.Client{Jar: cookieJar}
	if err != nil {
		log.Println(err)
		return nil, err
	}

	getReq, err := http.NewRequest("GET", loginURL.String(), nil)
	if err != nil {
		log.Println(err)
		return nil, err
	}

	if len(cookies) > 0 {
		for _, cookie := range cookies {
			getReq.AddCookie(cookie)
		}
	}
	getReq.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36")
	getReq.Header.Set("Referer", pageURL)
	fileRes, err := client.Do(getReq)
	if err != nil {
		log.Println(err)
		return nil, err
	}
	defer fileRes.Body.Close()

	//read file from response body to byte array
	file, err := io.ReadAll(fileRes.Body)
	if err != nil {
		return nil, err
	}
	// tt := string(file)
	// log.Println(tt)
	return file, err
}

func ParseXLS(file interface{}, headers map[string]string, skipRows int) (map[string][]string, error) {
	var xlFile xls.Workbook
	var err error
	headersIndex := make(map[string]int)
	var sheet *xls.Sheet
	data := make(map[string][]string)

	switch f := file.(type) {
	case string:
		if xlFile, err = xls.OpenFile(f); err != nil {
			return nil, err
		}
	case []byte:
		if xlFile, err = xls.OpenReader(bytes.NewReader(f)); err != nil {
			return nil, err
		}
	default:
		log.Fatal("Некорректный тип данных для параметра file")
		return nil, errors.New("Некорректный тип данных для параметра file")
	}
	if sheet, err = xlFile.GetSheet(0); err != nil {
		return nil, err
	}

	for i, row := range sheet.GetRows() {
		if i == skipRows && row != nil {
			for k, h := range headers {
				for j, col := range row.GetCols() {
					if col.GetString() == h {
						headersIndex[k] = j
					}
				}
			}
			continue
		} else if i < skipRows {
			continue
		}

		// headersKeys := make([]string, 0, len(headers))
		// for k, _ := range headers {
		// 	headersKeys = append(headersKeys, k)
		// }
		for h, i := range headersIndex {
			val, _ := row.GetCol(i)
			// log.Println(headers[h], val.GetString()) // debug
			data[h] = append(data[h], val.GetString())
		}

	}

	return data, nil
}

func ParseXLSX(file interface{}, headers map[string]string, skipRows int) (map[string][]string, error) {
	var xlFile *xlsx.File
	var err error
	headersIndex := make(map[string]int)
	data := make(map[string][]string)

	switch f := file.(type) {
	case string:
		xlFile, err = xlsx.OpenFile(f)
		if err != nil {
			return nil, err
		}
	case []byte:
		xlFile, err = xlsx.OpenBinary(f)
		if err != nil {
			return nil, err
		}
	default:
		log.Fatal("Некорректный тип данных для параметра file")
		return nil, errors.New("Некорректный тип данных для параметра file")
	}

	for i, row := range xlFile.Sheets[0].Rows {
		if i == skipRows {
			for k, h := range headers {
				for j, cell := range row.Cells {
					if cell.String() == h {
						headersIndex[k] = j
					}
				}
			}
			continue
		} else if i < skipRows {
			continue
		}

		for h, i := range headersIndex {
			data[h] = append(data[h], row.Cells[i].String())
		}

	}

	return data, nil
}

func FilterArray(array map[string][]string, filter func(string, string) bool) map[string][]string {
	filteredArray := make(map[string][]string)
	for k, v := range array {
		filteredValue := make([]string, 0)
		for _, v := range v {
			if filter(k, v) {
				filteredValue = append(filteredValue, v)
			}
		}
		if len(filteredValue) > 0 {
			filteredArray[k] = filteredValue
		}
	}
	return filteredArray
}

func ValidateDataOtchetPDChilds(data map[string][]string) (map[string][]string, error) {
	//deprecated
	filteredArray := FilterArray(data, func(key string, value string) bool {
		if key == "СНИЛС" || key == "СНИЛС заявителя" {
			if !IsValidSnils(value) || value == "" {
				return true
			}
		}
		if key == "Дата рождения заявителя" {
			if value == "" || value == "1970-01-01" || !IsValidBirthDate(value) {
				return true
			}
		}
		return false
	})

	return filteredArray, nil
}

// rrr, ww := parseExcel("/file.xlsx", []string{"qw","we"})
